#define NX_LOG_LEVEL NX_PrintfNFO

#include "input.h"
#include "wm.h"

#include <nxos.h>

WM_Input g_wm_input;

void WM_MouseMotion(int x_rel, int y_rel)
{
    g_wm_input.mouse_x += x_rel;
    g_wm_input.mouse_y += y_rel;
}

void WM_MouseWheel(int z_rel)
{
    WM_WheelMouseOnFocusWindow(g_wm_input.mouse_x, g_wm_input.mouse_y, 
        z_rel < 0 ? NX_MOUSEWHEELUP_EVENT : NX_MOUSEWHEELDOWN_EVENT);    
}

void WM_MouseButtonDown(int button)
{
    WM_FocusWindowByMouse(g_wm_input.mouse_x, g_wm_input.mouse_y, button);
}

void WM_MouseButtonUp(int button)
{
    WM_ReleaseMouseOnFocusWindow(g_wm_input.mouse_x, g_wm_input.mouse_y, button);
}

void WM_KeyboardDown(int keycode)
{
    if (keycode == NX_KEY_NUMLOCK)
    {
        if (g_wm_input.key_modify & NX_KMOD_NUM)
        {
            g_wm_input.key_modify &= ~NX_KMOD_NUM;
        }
        else
        {
            g_wm_input.key_modify |= NX_KMOD_NUM;    
        }
    }
    if (keycode == NX_KEY_CAPSLOCK) {
        if (g_wm_input.key_modify & NX_KMOD_CAPS)
        {
            g_wm_input.key_modify &= ~NX_KMOD_CAPS;
        }
        else
        {
            g_wm_input.key_modify |= NX_KMOD_CAPS;    
        }
    }
    
    /* handle CTRL, ALT, SHIFT */
    switch (keycode)
    {
    case NX_KEY_LSHIFT:    /* left shift */
        g_wm_input.key_modify |= NX_KMOD_SHIFT_L;
        break;
    case NX_KEY_RSHIFT:    /* right shift */
        g_wm_input.key_modify |= NX_KMOD_SHIFT_R;
        break;
    case NX_KEY_LALT:    /* left alt */
        g_wm_input.key_modify |= NX_KMOD_ALT_L;
        break;
    case NX_KEY_RALT:    /* right alt */
        g_wm_input.key_modify |= NX_KMOD_ALT_R;
        break;
    case NX_KEY_LCTRL:    /* left ctl */
        g_wm_input.key_modify |= NX_KMOD_CTRL_L;
        break;
    case NX_KEY_RCTRL:    /* right ctl */
        g_wm_input.key_modify |= NX_KMOD_CTRL_R;
        break;
    default:
        break;
    }

    WM_SendKeycode(NX_KEYDOWN_EVENT, keycode);
}

void WM_KeyboardUp(int keycode)
{
    /* handle CTRL, ALT, SHIFT*/
    switch (keycode)
    {
    case NX_KEY_LSHIFT:    /* left shift */
        g_wm_input.key_modify &= ~NX_KMOD_SHIFT_L;
        break;
    case NX_KEY_RSHIFT:    /* right shift */
        g_wm_input.key_modify &= ~NX_KMOD_SHIFT_R;
        break;
    case NX_KEY_LALT:    /* left alt */
        g_wm_input.key_modify &= ~NX_KMOD_ALT_L;
        break;
    case NX_KEY_RALT:    /* right alt */
        g_wm_input.key_modify &= ~NX_KMOD_ALT_R;
        break;
    case NX_KEY_LCTRL:    /* left ctl */
        g_wm_input.key_modify &= ~NX_KMOD_CTRL_L;
        break;
    case NX_KEY_RCTRL:    /* right ctl */
        g_wm_input.key_modify &= ~NX_KMOD_CTRL_R;
        break;
    default:
        break;
    }

    WM_SendKeycode(NX_KEYUP_EVENT, keycode);
}

NX_Error WM_InputInit(void)
{
    NX_Error err;

    g_wm_input.kbd_solt = NX_SOLT_INVALID_VALUE;
    g_wm_input.mouse_solt = NX_SOLT_INVALID_VALUE;
    g_wm_input.joystick_solt = NX_SOLT_INVALID_VALUE;

    if ((err = WM_InputKeyboardInit()) != NX_EOK)
    {
        NX_Printf("wm-input: init keyboard failed!\n");
    }
    if ((err = WM_InputMouseInit()) != NX_EOK)
    {
        NX_Printf("wm-input: init mouse failed!\n");
    }
    /* init joystick */
    if ((err = WM_InputJoystickInit()) != NX_EOK)
    {
        NX_Printf("wm-input: init joystick failed!\n");
    }
    return NX_EOK;
}

NX_Error WM_InputExit(void)
{
    WM_InputKeyboardExit();
    WM_InputMouseExit();
    WM_InputJoystickExit();
    return NX_EOK;
}
